package org.ands.data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.ands.crosswalk.CrossWalkEntry;
import org.ands.crosswalk.CrossWalkEntryRetrieverCSV;
import org.ands.data.IClientContentsRetriever.FileSubject;
import org.ands.input.IInputHelper;
import org.ands.input.IInputHelperFactory;
import org.ands.xml.DOMHelper;

public class ContentsRetrieverDataSetContainingContacts implements ISourceContentsRetriever {
	
	
	public ContentsRetrieverDataSetContainingContacts(){
		_registryObjectCount = 1;
	}
	
	public Map<Integer, List<Contents>> getXmlContentsFromSource(
			Map<FileSubject, String> crosswalkFilenames, 
			IInputHelperFactory inputHelperFactory) throws Exception {
		
		Map<Integer, List<Contents> > xmlContentsAllRegistryObjectsMap = new HashMap<Integer, List<Contents> >();
		
		while(inputHelperFactory.hasNextInputHelper()){
			
			System.out.println("hasNextInputHelper");
			
			try{
				IInputHelper inputHelper = inputHelperFactory.getNextInputHelper();
				xmlContentsAllRegistryObjectsMap.putAll(getXmlContentsPerDOM(inputHelper, crosswalkFilenames));
				
			}catch(Exception e){
				System.err.println("Failed to obtain xml - Exception: ["+e.getMessage()+"].\n");
				e.printStackTrace();
	
			}
			
			
		}
		
		
		return xmlContentsAllRegistryObjectsMap;
	}
	
	private Map<Integer, List<Contents> > getXmlContentsPerDOM(
			IInputHelper domHelper,
			Map<FileSubject, String> crosswalkFileNames) throws Exception{
		
		assert(domHelper != null);
		
		Map<Integer, List<Contents> > xmlContentsPerDOM = new HashMap<Integer, List<Contents> >();
		
		CrossWalkEntryRetrieverCSV crossWalkEntryRetrieverCSV = new CrossWalkEntryRetrieverCSV();
		ArrayList<Contents> collectionList = ContentsHelper.xmlContentsFromTree(
				domHelper, 
				crossWalkEntryRetrieverCSV.getCrossWalkEntryListFromFile(crosswalkFileNames.get(FileSubject.CROSSWALK_COLLECTION)), 
				_registryObjectCount);
		
		xmlContentsPerDOM.put(_registryObjectCount, collectionList);
		_registryObjectCount++;
		
		List<FileSubject> fileSubjectList = new ArrayList<FileSubject>();
		fileSubjectList.add(FileSubject.CROSSWALK_PARTY_CITED_GROUP);
		fileSubjectList.add(FileSubject.CROSSWALK_PARTY_CITED_PERSON);
		fileSubjectList.add(FileSubject.CROSSWALK_PARTY_CONTACT_GROUP);
		fileSubjectList.add(FileSubject.CROSSWALK_PARTY_CONTACT_PERSON);
		
		final int maxTries = 5;
		
		
		for(FileSubject subject : fileSubjectList){
			xmlContentsPerDOM.putAll(getXMLContentsPerParty(
					domHelper, 
					crossWalkEntryRetrieverCSV.getCrossWalkEntryListFromFile(crosswalkFileNames.get(subject)), 
					maxTries));
		}
		
		return xmlContentsPerDOM;
		
	}
	
	private Map<Integer, List<Contents> > getXMLContentsPerParty(IInputHelper domHelper, final ArrayList<CrossWalkEntry> partyCrossWalkEntryList, final int max) throws Exception{
		
		Map<Integer, List<Contents> > xmlContentsPerParty = new HashMap<Integer, List<Contents> >();
		
		int partyCount = 0;
		
		while(partyCount++ < max){
			ArrayList<CrossWalkEntry> partyCrossWalkEntryListIncremented = formatTreePathWithEntryCount(partyCrossWalkEntryList, partyCount);
			if((partyCrossWalkEntryListIncremented != null) && (!partyCrossWalkEntryListIncremented.isEmpty())){
				try{
					ArrayList<Contents> partyList = ContentsHelper.xmlContentsFromTree(domHelper, partyCrossWalkEntryListIncremented, _registryObjectCount);
					xmlContentsPerParty.put(_registryObjectCount, partyList);
	                _registryObjectCount++;
				}catch(Exception e){
					System.err.println("Failed to construct party "+partyCount+" for collection Exception: ["+e.getMessage()+"]. Trying next party.\n");
				}
			}
		}
		
		return xmlContentsPerParty;
	}
	
	/**
	 * Party crosswalk files have format specifier %s in treePath because we are required to iterate through
	 * occurrences of responsible parties.  
	 *
	 * @return the xml contents
	 * @throws Exception the exception
	 */
	private ArrayList<CrossWalkEntry> formatTreePathWithEntryCount(final ArrayList<CrossWalkEntry> partyCrossWalkEntryList, final int entryCount){
		
		assert(entryCount > 0); 
		
		ArrayList<CrossWalkEntry> listFormatted = new ArrayList<CrossWalkEntry>();
		
		for(final CrossWalkEntry entry: partyCrossWalkEntryList){
			CrossWalkEntry formattedEntry = new CrossWalkEntry(entry);
			assert(formattedEntry.getTreePath().equals(entry.getTreePath()));
			String treePath = formattedEntry.getTreePath();
			System.out.println("Tree path "+treePath);
			if(treePath.length() > 0){
				assert(treePath.contains("%s"));
				assert(treePath.indexOf("%s") == treePath.lastIndexOf("%s"));
				formattedEntry.setTreePath(String.format(treePath, String.valueOf(entryCount)));
				assert(!(formattedEntry.getTreePath().contains("%s")));
			}
			
			listFormatted.add(formattedEntry);
		}
		
		assert(listFormatted.size() == partyCrossWalkEntryList.size());
		return listFormatted;
	}
	
	private int _registryObjectCount;

}
